/**
 * @author Camaria Bevavy
 * 
 * build xml document from bson objects
 * need collectionname for xml document root
 * receive bson object to build xml nodes
 */
package com.mongoproject.database;
import java.io.*;
import org.w3c.dom.*;
import com.mongodb.DBObject;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import java.text.SimpleDateFormat;
import java.util.*;

public class XmlBuilder {
	private String doc_name;
	private String root_name;
	
	/**
	 *  @param docname: collection name
	 */
	public XmlBuilder(String docname){
		this.doc_name = docname;
		root_name = docname;
	}
	
	/**
	 * create a root for the view document
	 * @param name of root
	 */
	public void setRoot(String name){
		root_name =  name;
	}
	
	/**
	 * strip spaces and unwanted characters from a string
	 * @param s: string query
	 * @return formatted query
	 */
	private String formatString(String s){
		s = s.replaceAll("[\\[{\\]}\"'_]", " ");
		
		s = s.trim();
		return s;
	}

	/**
	 * build an xml document from a list of query result
	 * the view name is built from concatenating a timestamp and collection name
	 * @param obj_list : list of DBObject from Mongodb
	 */
	public String xmlBuild(List<DBObject> obj_list){
		String filename = null;
		Date d = new Date();
		SimpleDateFormat frm = new SimpleDateFormat("MM_dd_yyyy_h_mm_ss_a");
		String timestamp =  frm.format(d);
		/**
		 * XML VARIABLES
		 */
		DocumentBuilder docbuilder = null;
		Transformer transform = null;
		Document new_doc = null;
		
		try {
			DocumentBuilderFactory docfactory = DocumentBuilderFactory.newInstance();
			docbuilder = docfactory.newDocumentBuilder();
		}
		catch(ParserConfigurationException e){
			e.printStackTrace();
		}
		
		new_doc = docbuilder.newDocument();
		
		//create big parent
		Element root = new_doc.createElement(root_name + "view");
		new_doc.appendChild(root);
		
		/**
		 * REGULAR VARIABLES
		 */
		int x = 0;
		int y = 0;
		Set obj_set = new TreeSet();
		String o;
		String[] fields;
		String[] nests;
		String[] tag_value;
		
		if(docbuilder != null)
		{
			for(x = 0; x < obj_list.size(); x++){
				
				String parent = root_name;
				Element child_parent = new_doc.createElement(parent);
				
				obj_set = obj_list.get(x).toMap().entrySet(); //create a set
				
				//create an array
				Object[] obj_arr =  obj_set.toArray();
				
				for(y = 0; y < obj_arr.length; y++){
					o = obj_arr[y].toString();
					fields = o.split("=");
					
					//first tag element
					fields[0] = formatString(fields[0]);
					Element child_node = new_doc.createElement(fields[0]);
					
					//check fields[1] for nested array
					boolean nesting = checkNesting(fields[1]);
					
					if(nesting){
						
						//split 
						nests = fields[1].split(",");
						
						for(String s : nests){
							tag_value = s.split(":");
							
							//tag
							tag_value[0] = formatString(tag_value[0]);
							Element nested_node = new_doc.createElement(tag_value[0]);
							
							//value
							tag_value[1] = formatString(tag_value[1]);
							Text nested_text = new_doc.createTextNode(tag_value[1]);
							
							//append value
							nested_node.appendChild(nested_text);
							
							//append new node
							child_node.appendChild(nested_node);
						}
					}
					else{
						fields[1] = formatString(fields[1]);
						Text child_text = new_doc.createTextNode(fields[1]);
						child_node.appendChild(child_text);					
					}
					
					//append new content inside
					child_parent.appendChild(child_node);
					//apend to root
					root.appendChild(child_parent);
				}
				
			}//end of outer loop	
			
		} //end if docbuilder != null
		
		try{
			TransformerFactory tFactory = TransformerFactory.newInstance();
			transform = tFactory.newTransformer();
			transform.setOutputProperty(OutputKeys.INDENT, "yes");
		}
		catch(TransformerConfigurationException e){
			System.out.println(e.getMessage());
		}
		
		if(transform != null){
			DOMSource xml_source = new DOMSource(new_doc);			
			
			filename = doc_name + timestamp + ".xml";
			File xml_file = new File(filename);
			StreamResult xml_doc = new StreamResult(xml_file);
			//StreamResult xml_doc = new StreamResult(System.out);
			
			try{
				transform.transform(xml_source, xml_doc);
			}
			catch(TransformerException e){
				e.printStackTrace();
			}
		}
		
		 return filename;
	}

	/**
	 * check if a query result contains array or sub documents
	 * @param field: one line in a query result
	 * @return true if sub document found; false otherwise
	 */
	public boolean checkNesting(String field){
		boolean nested = false;
		if(field.contains(":")){
			nested = true;
			//System.out.println(field);
		}
		
		return nested;
	}
	

}
